home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Turnbull China Bikeride
/
Turnbull China Bikeride - Disc 2.iso
/
STUTTGART
/
UTIL
/
MEMORY
/
OLD
/
MEM208SRC
/
!Memphis
/
c
/
Lfile
< prev
next >
Wrap
Text File
|
1993-09-09
|
9KB
|
369 lines
/*
* Lfile.c
* Part of the !Memphis distribution
* (c) bdb/nas, 1991-3
*/
/* #define DEBUG */
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "kernel.h"
#include "swis.h"
#include "_swis.h"
#include "util.h"
#include "compress.h"
/* debug support */
#ifdef DEBUG
#define DEBUGF printf
#else
#define DEBUGF 1?(void)0:(void)printf
#endif
static int ftruncate(int fp,int len)
{ return _kernel_osargs(3,fp,len)==_kernel_ERROR?EOF:0;
}
static int read(int fd, void *buff, int nbytes)
{ if (_swix(OS_GBPB,_INR(0,3)|_OUT(3),4,fd,buff,nbytes,&fd))
return EOF;
return nbytes-fd;
}
static int write(int fd, void *buff, int nbytes)
{ if (_swix(OS_GBPB,_INR(0,3)|_OUT(3),2,fd,buff,nbytes,&fd))
return EOF;
return nbytes-fd;
}
static int readat(int fd, int offset, void *buff, int nbytes)
{ if (_swix(OS_GBPB,_INR(0,4)|_OUT(3),3,fd,buff,nbytes,offset,&fd))
return EOF;
return nbytes-fd;
}
static int writeat(int fd, int offset, void *buff, int nbytes)
{ if (_swix(OS_GBPB,_INR(0,4)|_OUT(3),1,fd,buff,nbytes,offset,&fd))
return EOF;
return nbytes-fd;
}
#define OREAD 0
#define OCREATE 1
#define OREADWRITE 2
static int open(char *name,int mode)
{ if (mode<0 || mode>2)
return EOF;
if (_swix(OS_Find,_IN(0)|_IN(1)|_OUT(0),0x4f+mode*0x40,
name,&mode))
return EOF;
return mode;
}
static int close(int fd)
{ if (_swix(OS_Find,_IN(0)|_IN(1),0,fd))
return EOF;
return 0;
}
#define L_SET 0
#define L_INCR 1
#define L_XTND 2
static int lseek(int fd,int offset,int whence)
{ switch (whence)
{ case L_SET:
break;
case L_INCR:
whence = _kernel_osargs(0,fd,0);
if (whence==_kernel_ERROR) return EOF;
offset += whence;
break;
case L_XTND:
whence = _kernel_osargs(2,fd,0);
if (whence==_kernel_ERROR) return EOF;
offset += whence;
break;
default:
return EOF;
}
return _kernel_osargs(1,fd,offset)==_kernel_ERROR?EOF:offset;
}
static DEFERR(mb_memory,0,"Out of memory");
static DEFERR(mb_NotFound,0,"Lump file not found");
static DEFERR(mb_Read,0,"Lump file read failed");
static DEFERR(mb_Create,0,"Could not create Lump file");
static DEFERR(mb_Write,0,"Lump file write failed");
#include "Lfile.h"
#define PAGESIZE 32768 /* Lumps we compress data in */
struct extent { int offset, len; }; /* a len of 0 means this extent isn't used */
struct lhandle
{ int size; /* Uncompressed size of the file */
int numpages; /* amount of memory currently allocated */
struct extent *pages; /* where in file corresponds to each page */
int changed:1; /* Whether changed since opened */
int fp; /* os file handle */
};
/* The format of a Lfile is as follows
* Each 32K page of data is compressed separately, and stored as an extent in the file
* When the file is closed, the index of these is stored at the end of the file, followed
* by its uncompressed length (which tells how many extents there are
*/
static char *pagebuf;
static char *compressbuf;
static int pbpage;
static LHANDLE pbhandle;
static int pbchanged;
static _kernel_oserror *putpage(LHANDLE h,int page)
{ int i;
struct extent e;
DEBUGF("putpage: %p %d...",h,page);
DEBUGF("size %d\n", h->size);
if (h->size < PAGESIZE)
e.len = compress(pagebuf,h->size,compressbuf,PAGESIZE);
else
e.len = compress(pagebuf,PAGESIZE,compressbuf,PAGESIZE);
DEBUGF("compress to %d,",e.len);
h->changed = 1;
e.offset = 0;
lp:
for (i=0;i<h->numpages;i++)
if (i!=page && ( e.offset>=h->pages[i].offset ? e.offset < h->pages[i].offset+h->pages[i].len :
h->pages[i].offset < e.offset+e.len ))
{ e.offset = h->pages[i].offset+h->pages[i].len;
goto lp;
}
h->pages[page] = e;
DEBUGF("offset=%x,",e.offset);
if (writeat(h->fp,e.offset,compressbuf,e.len)!=e.len)
return ERR(mb_Write);
pbchanged = 0;
DEBUGF("ok\n");
return NULL;
}
static _kernel_oserror *getpage(LHANDLE h,int page)
{ _kernel_oserror *err;
struct extent e;
DEBUGF("getpage: %p %d...",h,page);
if (pbhandle==h && pbpage==page)
{ DEBUGF("bufferd ok\n");
return NULL;
}
if (pbhandle && pbchanged)
{ err = putpage(pbhandle,pbpage);
if (err) return err;
}
e = h->pages[page];
if (e.len)
{ if (readat(h->fp,e.offset,compressbuf,e.len)!=e.len)
return ERR(mb_Read);
DEBUGF("read offset %x+%d size %d,",e.offset,e.len,h->size);
if (h->size == e.len)
uncompress(compressbuf,e.len,pagebuf,e.len);
else
uncompress(compressbuf,e.len,pagebuf,PAGESIZE);
}
else
memset(pagebuf,0,PAGESIZE);
pbhandle = h;
pbpage = page;
pbchanged = 0;
DEBUGF("ok\n");
return NULL;
}
/* #undef DEBUGF
#define DEBUGF 1?(void)0:(void)printf
*/
_kernel_oserror *Linit(void)
{
DEBUGF("Linit....");
pagebuf = malloc(PAGESIZE);
pbhandle = NULL;
compressbuf = malloc(PAGESIZE);
if (!pagebuf || !compressbuf)
return ERR(mb_memory);
DEBUGF("ok\n");
return NULL;
}
_kernel_oserror *Lfinish(void)
{
DEBUGF("Lfinish...");
if (pbhandle && pbchanged)
putpage(pbhandle,pbpage);
free(pagebuf);
free(compressbuf);
DEBUGF("ok\n");
return NULL;
}
_kernel_oserror *Lcreate(char *filename,int length)
{ int fp;
struct extent e;
int n;
DEBUGF("Lcreate %s %d...",filename,length);
fp = open(filename,OCREATE);
if (fp==EOF)
return ERR(mb_Create);
n = (length + PAGESIZE-1)/PAGESIZE;
e.offset = e.len = 0;
for (;n--;)
if (write(fp,&e,sizeof(struct extent))==EOF)
goto erk;
if (write(fp,&length,sizeof(int))==EOF)
goto erk;
close(fp);
DEBUGF("ok\n");
return NULL;
erk:
close(fp);
remove(filename);
return ERR(mb_Write);
}
_kernel_oserror *Lopen(char *filename, LHANDLE *h)
{
LHANDLE p=malloc(sizeof(struct lhandle));
int k;
DEBUGF("Lopen %s..",filename);
if (!p)
return ERR(mb_memory);
p->fp = open(filename,OREADWRITE);
if (p->fp==EOF)
return ERR(mb_NotFound);
k = sizeof(p->size);
if (lseek(p->fp,-k,L_XTND)==EOF ||
read(p->fp,&p->size,k)!=k)
return ERR(mb_Read);
p->numpages = (p->size + PAGESIZE-1)/PAGESIZE;
DEBUGF("size %d, pages=%d..",p->size,p->numpages);
k = sizeof(struct extent)*p->numpages;
p->pages = malloc(k);
p->changed = 0;
if (!p->pages)
{
close(p->fp);
free(p);
return ERR(mb_memory);
}
if (lseek(p->fp,-sizeof(p->size)-k,L_XTND)==EOF ||
read(p->fp,p->pages,k)!=k)
return ERR(mb_Read);
*h=p;
DEBUGF("=%p ok\n",p);
return NULL;
}
_kernel_oserror *Lclose(LHANDLE h)
{ _kernel_oserror *err=NULL;
int i,m,k;
m = 0;
DEBUGF("Lclose %p...",h);
if (pbhandle==h && pbchanged)
putpage(h,pbpage);
if (h->changed)
{
for (i=0;i<h->numpages;i++)
if (m<h->pages[i].offset+h->pages[i].len)
m = h->pages[i].offset+h->pages[i].len;
k = sizeof(struct extent)*h->numpages;
if (writeat(h->fp,m,h->pages,k)!=k ||
write(h->fp,&h->size,sizeof(int))!=sizeof(int) ||
ftruncate(h->fp,m+k+sizeof(int))==EOF)
err = ERR(mb_Write);
}
close(h->fp);
free(h->pages);
free(h);
if (pbhandle==h)
pbhandle = NULL;
DEBUGF("ok\n");
return err;
}
_kernel_oserror *Lread(LHANDLE h,int offset,int len, char *ptr)
{ _kernel_oserror *err;
int page,o,l;
DEBUGF("Lread %p %x+%x %p..",h,offset,len,ptr);
lp:
page = offset/PAGESIZE;
o = offset % PAGESIZE;
err = getpage(h,page);
if (err) return err;
l = PAGESIZE - o;
if (l>len) l = len;
memcpy(ptr,&pagebuf[o],l);
if (l<len)
{ len -= l;
offset += l;
ptr = (char *)ptr + l;
goto lp;
}
DEBUGF("ok\n");
return NULL;
}
_kernel_oserror *Lwrite(LHANDLE h,int offset,int len, char *ptr)
{ _kernel_oserror *err;
int page,o,l;
DEBUGF("Lwrite %p %x+%x %p..",h,offset,len,ptr);
lp:
page = offset/PAGESIZE;
o = offset % PAGESIZE;
err = getpage(h,page);
if (err) return err;
l = PAGESIZE - o;
if (l>len) l = len;
memcpy(&pagebuf[o],ptr,l);
pbchanged = 1;
if (l<len)
{ len -= l;
offset += l;
ptr = (char *)ptr + l;
goto lp;
}
DEBUGF("ok\n");
return NULL;
}
_kernel_oserror *Lsetlength(LHANDLE h,int len)
{ int newnumpages = (len + PAGESIZE-1)/PAGESIZE;
int i;
struct extent *newpages;
DEBUGF("Lsetlength %p %x...",h,len);
if (pbhandle==h && pbchanged)
putpage(h,pbpage);
if (pbhandle==h)
pbhandle=NULL;
h->changed = 1;
if (h->numpages==newnumpages)
{ h->size = len;
DEBUGF("pages same ok\n");
return NULL;
}
newpages = malloc(sizeof(struct extent)*newnumpages);
if (!newpages)
return ERR(mb_memory);
memcpy(newpages,h->pages,sizeof(struct extent)*newnumpages);
for (i=h->numpages;i<newnumpages;i++)
newpages[i].len = 0;
free(h->pages);
h->size = len;
h->pages = newpages;
h->numpages = newnumpages;
DEBUGF("ok\n");
return NULL;
}